<?php

namespace app\admin\controller;

use app\admin\model\Goods as GoodsModel;
use app\admin\model\GoodsAttr;
use app\common\controller\Backend;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\exception\PDOException;
use think\exception\ValidateException;
use think\facade\Db;

/**
 * 商品列管理
 *
 */
class Goods extends Backend
{
    /**
     * Goods模型对象
     * @var GoodsModel
     */
    protected $model = null;

    protected $quickSearchField = ['id'];

    protected $defaultSortField = 'id,desc';

    protected $withJoinTable = ['category', 'coupon'];

    protected $preExcludeFields = ['createtime', 'updatetime'];

    public function initialize()
    {
        parent::initialize();
        $this->model = new GoodsModel;
    }

    public function index()
    {
        $this->request->filter(['strip_tags', 'trim']);
        if ($this->request->param('select')) {
            $this->select();
        }

        [$where, $alias, $limit, $order] = $this->queryBuilder();
        $res = $this->model
            ->withJoin($this->withJoinTable, $this->withJoinType)
            ->alias($alias)
            ->where($where)
            ->order($order)
            ->paginate($limit);

        $this->success('', [
            'list'   => $res->items(),
            'total'  => $res->total(),
            'remark' => get_route_remark(),
        ]);
    }

    /**
     * @param $id
     * @param GoodsModel $goods
     * @param GoodsAttr $attrModel
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function attr($id, GoodsModel $goods, GoodsAttr $attrModel)
    {
        $row = $this->model->find($id);
        if (!$row) {
            $this->error(__('Record not found'));
        }

        if ($this->request->isPost()) {
            $data = $this->request->post();
            if (!$data) {
                $this->error(__('Parameter %s can not be empty', ['']));
            }

            $data = $this->excludeFields($data);
            $result = false;
            Db::startTrans();
            try {
                $stock = 0;
                $ids = $attrModel->where(['goods_id' => $id])->column('id');
                foreach ($data['attrValue'] as $v) {
                    $stock += $v['stock'];
                    $attrData = [
                        'goods_id' => $id,
                        'price'    => $v['price'],
                        'stock'    => $v['stock'],
                        'image'    => $v['image'],
                        'key'      => $v['key'],
                    ];
                    $attr = $attrModel->where(['goods_id' => $id, 'key' => $v['key']])->find();
                    if ($attr) {
                        $k = array_search($attr['id'], $ids);
                        if (isset($k)) {
                            unset($ids[$k]);
                        }
                    } else {
                        $attr = new GoodsAttr();
                    }
                    $attr->save($attrData);
                }
                $attrModel->whereIn('id', $ids)->select()->delete();
                $goods->where(['id' => $id])->update([
                    'attr_keys' => json_encode($data['attr'] ?? [], 256),
                    'stock'     => $stock,
                ]);
                $result = true;
                Db::commit();
            } catch (ValidateException $e) {
                Db::rollback();
                $this->error($e->getMessage());
            } catch (PDOException $e) {
                Db::rollback();
                $this->error($e->getMessage());
            } catch (Exception $e) {
                Db::rollback();
                $this->error($e->getMessage());
            }
            if ($result !== false) {
                $this->success(__('Update successful'));
            } else {
                $this->error(__('No rows updated'));
            }

        }

        $attrKeys = json_decode($row['attr_keys'], true);
        $attrData = $attrModel
            ->where(['goods_id' => $id])
            ->hidden(['createtime', 'delete_time', 'goods_id', 'id'])
            ->select()
            ->each(function ($item) use ($attrKeys) {
                $attr = explode(',', $item['key']);
                foreach ($attr as $k => $v) {
                    $item[$attrKeys[$k]['name']] = $v;
                }
                return $item;
            });

        $this->success('', [
            'row' => [
                'id'        => $id,
                'attr'      => $attrKeys,
                'attrValue' => $attrData,
            ],
        ]);
    }

}